/*******************************************************************************

                                SPEDEN

  Title:        Controller for Speden - the solver and its utilities.
  Author:       Hanna Szoke
  Date:         5/10/2001
  Function:     This controller calls one of the following:

		apodfc		apodfo 		back
		bin2hdf		distance 	hdf2bin		
		maketar		perturbhkl 	regrid		
		solve		weedfc		weedfo
		variance

DISCLAIMER

This software was prepared as an account of work sponsored by an
agency of the United States Government.  Neither the United States Government
nor the University of California nor any of their employees, makes any
warranty, express or implied, or assumes any liability or responsibility for
the accuracy, completeness, or usefulness of any information, apparatus,
product, or process disclosed, or represents that its use would not infringe
privately-owned rights.  Reference herein to any specific commercial products,
process, or service by trade name, trademark, manufacturer, or otherwise, does
not necessarily constitute or imply its endorsement, recommendation, or
favoring by the United States Government or the University of California.  The
views and opinions of authors expressed herein do not necessarily state or
reflect those of the United States Government or the University of California,
and shall not be used for advertising or product endorsement purposes.

*******************************************************************************/


#include "util.h"

FILE    *fp_log ; 	

char	log_filename[MAXSTRING] ;
char	caller[MAXSTRING] ;	
char	command_line[MAXSTRING] ;

int	batch ;
int	silent ;
int	verbose ;
int	very_verbose ;
int	interactive ;
int	graphics ;	
int	quick ;
int	oneIt ;
float	t0, t1, t2, t3, t4, t5, t6 ;

static	int	check_switches(int, char *[]) ;
static	void   	get_unique_logname() ;
static	int	valid_name(char *) ;

typedef struct {
  char name[25];
  int  nwarn;
  speden_method *em;
  char *warning;
} method;

method methods[] = {
  { "apodfc",	    0, apodfc_main,	NULL},	   
  { "apodfo",	    0, apodfo_main,	NULL},	   
  { "back",	    0, back_main,	NULL},	   
  { "bin2hdf",	    0, bin2hdf_main,	NULL},	   
  { "distance",     0, distance_main,	NULL},   
  { "hdf2bin",	    0, hdf2bin_main,	NULL},	   
  { "maketar",	    0, maketar_main,	NULL},	   
  { "perturbhkl",   0, perturbhkl_main,	NULL}, 
  { "regrid",	    0, regrid_main,	NULL},	   
  { "solve",	    0, solve_main,	NULL},	   
  { "variance",     0, variance_main,	NULL},   
  { "weedfc",       0, weedfc_main,	NULL},   
  { "weedfo",       0, weedfo_main,	NULL},   
  { "interrupt",    0, NULL, NULL},
  { "keywords",     0, NULL, NULL},
  { "news",         0, NULL, NULL},
  { "switches",     0, NULL, NULL}
};
int   Nmethod = (sizeof(methods)/sizeof(methods[0])) ;

int	check_switches(int argc, char *argv[])
{
  /******************************************************
  Check switches: everybody can ask for help and many 
  programs have a meaningful 'verbose' at 2 levels.
  Flag 'graphics' enables call to xmgr in apodfo/c.
  ******************************************************/

     int	ch ;
     int	send_help =FALSE ;

     batch = FALSE ;
     silent = FALSE ;
     interactive = FALSE ;
     oneIt = FALSE ;
     verbose = TRUE ;
     very_verbose = FALSE ;
     graphics = TRUE ;
     quick = FALSE ;

     /******************************************************
     Note: getopt() provides EDEN with variable 'optind'
     which appears throughout the code.  See man getopt.
     ******************************************************/

     while ((ch = getopt(argc, argv, "bghinosvV")) != EOF) 
     {
       switch(ch)
       {
       case 'b':
            batch = TRUE ;
	    break ;
       case 'g':
	    graphics = TRUE ;
	    break ;
       case 'h':
            send_help = TRUE ;
	    break ;
       case 'i':	/* 11/05: unused & undocumented in 'help' */
            interactive = TRUE ;
	    break ;
       case 'n':
	    graphics = FALSE ;
	    break ;
       case 'o':
            oneIt = TRUE ;
	    break ;
       case 's':
            silent = TRUE ;
	    break ;
       case 'v':
            verbose = TRUE ;
	    break ;
       case 'V':
            very_verbose = TRUE ;
            verbose = TRUE ;
	    break ;
       default:
	    break ;
       }
    }
    return(send_help) ;
}
          

int	valid_name(char *caller) 
{
     int i;

  for(i=0; (i<Nmethod); i++) {
    if (strcmp(caller,methods[i].name) == 0) {
      if (methods[i].nwarn > 0)
	printf("WARNING: %s\n",methods[i].warning);
      if (methods[i].nwarn < 2)
	return TRUE;
    }
  }
     printf("\n\t%s: No such program in Speden\n", caller) ;

     ballpark("speden") ;  
     return FALSE ;
}

void	get_unique_logname()
{   
     int	j ;
     FILE	*fpin ;
     char	*cwd ;

     /* Try the basic name - [caller].log */

     sprintf(log_filename, "%s.log", caller) ;

     if ((!batch) && ((fpin = fopen(log_filename, "r")) != NULL)) {
     
     /* Basic name is in use; find first free name of form [caller][j].log */

	 for (j = 1; j < 10; j++) {

             sprintf(log_filename, "%s%1d.log", caller, j) ;

             if ((fpin = fopen(log_filename, "r")) == NULL) 
	          break ;
             else
                  fclose(fpin) ;
         }

         /* Fall-through; all names are in use - exit with error */

         if (j == 9) {
              fprintf(stderr, "\nThere are no more free names for a log!\n") ;
	      exit(-1) ;	/* Can't call Fatal yet*/
         }

     }
     if ((fp_log = fopen(log_filename,"w")) == NULL) 
     {
          fprintf(stderr, "Cannot open %s\n", log_filename);
          exit(-1);
     }
     else
          fprintf(fp_log, "\n\t\t\t%s\n\n", log_filename) ;

     if ((cwd = getcwd(NULL, 120)) == NULL) 
	  Fatal("Can't get pwd") ;

     fprintf(fp_log, "\nRunning Single Particle Eden from %s\n", cwd) ;
     free(cwd) ;

     return;    
}

int	main(int argc, char *argv[])
{
     void	help(char *) ;
     void	end_record(int);

     int	send_help ;
     int	k ;

     send_help = check_switches(argc, argv) ;

  /******************************************************
  Check existence of environmental variable SPEDENHOME.
  If user types only "speden" or "speden -h", provide a 
  brief overview and quit. Otherwise, decide what's called.
  Note that exits - good or bad - cannot be put into
  the record file because it hasn't yet been established!
  ******************************************************/

     if (getenv("SPEDENHOME") == NULL) {
	  fprintf(stderr, 
	    "Please set environment variable SPEDENHOME before running speden!\n") ;
	  exit(-1) ;
     }

     if ( (argc == 1) || ((argc == 2) && (optind == 2))) 
	  ballpark("speden") ;  
     
     strcpy(caller, argv[optind]) ;

     for (k=0; k<(int) strlen(caller); k++)
          caller[k] = tolower((int) caller[k]) ;

     if (!valid_name(caller))
	  exit(-1) ;

  /******************************************************
  Deal with a request for help.  Note: users may get help 
  for "keywords" and "switches" even though they're not 
  legal programs.
  ******************************************************/

     if (send_help) {
          help(caller) ;
	  exit(0) ;
     }

  /******************************************************
  Deal with e.g.  "speden regrid" (no arg list).  
  Calls to ballpark() are terminal.
  ******************************************************/

     if ((argc == 2) && (optind == 1)) 
	  ballpark(caller) ;  

  /******************************************************
  Prepare a log file, echo pwd & input line to the log.
  Identify parameter file name (which may or may not 
  have the .inp extension).
  ******************************************************/

     get_unique_logname() ;

     sprintf(command_line, argv[0]) ;

     for (k = 1; k < argc; k++) { 
         strcat(command_line, " ") ;
         strcat(command_line, argv[k]) ;
     }

     fprintf(fp_log, "Command line: %s\n", command_line) ;
     fflush(fp_log) ;

     sprintf(input_filename, "%s", argv[optind+1]) ;
     if (strstr(input_filename, ".inp") == NULL)
	  strcat(input_filename, ".inp") ;

  /******************************************************
  Finally: go do it!
  ******************************************************/

     for(k=0; (k<Nmethod); k++) {
          if (strcmp(caller,methods[k].name) == 0) {
              methods[k].em(argc,argv);
       }
     }
	
     if (!silent)
	  printf("A log of this run has been written to %s\n", log_filename) ;

     printTwice("\n") ;
     printTwice(timestamp()) ;
     printTwice("\n") ;

     end_record(0) ;		/* end_record exits. */
     exit(0) ;		/* not reached; compiler warns in its absence */
}
